using CfgTable;
using Cysharp.Threading.Tasks;
using IQIGame.Onigao.Framework;
using IQIGame.Onigao.Game;
using NetProtocol.Enum;
using UnityEngine;

namespace IQIGame.Onigao.GamePlay
{
    public class LevelNormalEntity : LevelPlayRealityEntity
    {
        public override uint MaxStore => 100;

        private byte _oldInteractType;
        /// <summary>
        /// 任务叹号特效
        /// </summary>
        private Entity _questMarkEffect;
        /// <summary>
        /// 当前是否有可接取的任务
        /// </summary>
        private bool _isExistActiveQuest;

        public DynLevelEntity dynEntity { protected set; get; }

        public override float x => dynEntity.x;

        public override float y => dynEntity.y;

        public override float z => dynEntity.z;

        public override int dirEuler => dynEntity.dirEuler;

        public override byte interactType => dynEntity.interactType; // LevelEntityInteractType.Talk;

        public override CfgPhysicalEntity cfgEntity => dynEntity.cfgLevelEntity;

        public override bool active => dynEntity.active;

        public override BVHBounds2D bvhBounds { get; set; }
        public override string name => dynEntity.name;
        public override int viewRange => dynEntity.levelEntityConfig.viewRange;
        public override int viewAngle => dynEntity.levelEntityConfig.viewAngle;

        private void Init(DynLevelEntity dynEntity)
        {
            this.dynEntity = dynEntity;
        }

        public static LevelNormalEntity CreateEntity(DynLevelEntity dynEntity)
        {
            var entity = ClassPool<LevelNormalEntity>.Get();
            entity.Init(dynEntity);
            entity.OnEntityCreate();
            return entity;
        }

        public override DynLevelEntity GetDynLevelEntity()
        {
            return dynEntity;
        }

        public override LevelBuffHolder GetBuffHolder()
        {
            return dynEntity.buffHolder;
        }

        public override void EntityAddComponents()
        {
            this.AddComponentWithPool<LevelMoveComponent>(ETComponentType.EntityMove);
            this.AddComponentWithPool<EntityUIViewComponent>(ETComponentType.EntityUIView);
            this.AddComponentWithPool<LevelAnimationComponent>(ETComponentType.EntityAnimation);
            this.AddComponentWithPool<EntityBindPointComponent>(ETComponentType.EntityBindPoint);
            this.AddComponentWithPool<LevelEntityAudioComponent>(ETComponentType.EntityAudio);
            this.AddComponentWithPool<LevelBuffDisplayComponent>(ETComponentType.EntityBuffDisplay);
        }

        protected override string GetEntityLoadPath()
        {
            return PathConstant.GetEntityLevelPrefabPath(dynEntity.cfgLevelEntity.EntityAsset);
        }

        public override void SyncEntityPos(float x, float y, float z, float speedRatio, EntityMoveDirType dirType, LevelMoveReason reason)
        {
            dynEntity.UpdatePos(x, y, z);
            UnityEngine.Vector3 targetPosition;
            if (reason == LevelMoveReason.TakeElevator)
            {
                targetPosition = GameMathUtil.LogicPos2UnityPos(dynEntity.x, dynEntity.y, dynEntity.z);
            }
            else
            {
                targetPosition = LevelPlayUtil.GetAdjustedPosByGround(dynEntity.x, dynEntity.y, dynEntity.z);
            }
            if (reason == LevelMoveReason.Move || reason == LevelMoveReason.TakeElevator)
            {
                this.GetMoveComponent().SetSmoothMoveTarget(targetPosition, speedRatio, dirType);
            }
            else
            {
                this.GetMoveComponent().TransferLocation(targetPosition);
            }
        }

        public override void SetEntityActive(bool active)
        {
            this.dynEntity.SetActive(active);
            this.gameObject?.SetActive(active);
            base.SetEntityActive(active);
        }

        public override bool ContainTag(ushort tagId)
        {
            return dynEntity.tags.Contains(tagId);
        }

        public void SetInteractType(byte type)
        {
            _oldInteractType = dynEntity.interactType;
            dynEntity.SetInteractType(type);
        }

        public void RecoverInteractType()
        {
            dynEntity.SetInteractType(_oldInteractType);
            _oldInteractType = 0;
        }

        public override void UpdatePosToData(Vector3 position)
        {
            Vector3 logicPos = GameMathUtil.UnityPos2LogicPos(position);
            dynEntity.UpdatePos(logicPos.x, logicPos.y, logicPos.z);
        }

        /// <summary>
        /// 刷新任务状态
        /// </summary>
        public override void RefreshQuestState()
        {
            base.RefreshQuestState();
            SetQuestState(this.IsOfferingQuest()).Forget();
        }

        /// <summary>
        /// 设置任务状态
        /// </summary>
        /// <param name="isExistActiveQuest"></param>
        /// <returns></returns>
        private async UniTaskVoid SetQuestState(bool isExistActiveQuest)
        {
            _isExistActiveQuest = isExistActiveQuest;
            if (isIndicatorOnMe) //如果头上已经显示交互指示器，当前一定不会有叹号显示
            {
                return;
            }
            await SetQuestMarkActive(isExistActiveQuest);
        }

        /// <summary>
        /// 显示或隐藏叹号特效
        /// </summary>
        /// <param name="isActive"></param>
        /// <returns></returns>
        private async UniTask SetQuestMarkActive(bool isActive)
        {
            if (isActive && _questMarkEffect == null)
            {
                _questMarkEffect = await LevelPlayModule.Instance.levelPlay.regionCtrl.effectCtrl.ShowEntityEffect(this, EntityBindPointCommonType.Top, ViewEntityConst.QuestMarkEffectResId);
            }
            else if (!isActive && _questMarkEffect != null)
            {
                LevelPlayModule.Instance.levelPlay.regionCtrl.effectCtrl.HideEntityEffect(this, ViewEntityConst.QuestMarkEffectResId);
                _questMarkEffect = null;
            }
        }

        /// <summary>
        /// 头顶交互指示器改变
        /// </summary>
        /// <param name="isIndicatorOnMe"></param>
        public override void OnIndicatorChange(bool isIndicatorOnMe)
        {
            base.OnIndicatorChange(isIndicatorOnMe);
            if (_isExistActiveQuest) //如果当前有可接取任务，需根据指示器是否在头上改变任务叹号的显示
            {
                //任务叹号和指示器互斥，且指示器优先级更高
                SetQuestMarkActive(!isIndicatorOnMe).Forget();
            }
        }

        #region 属性

        public override int GetDefaultSpeed()
        {
            return dynEntity.cfgLevelEntity.DefaultSpeed;
        }

        #endregion

        public override void OnReset()
        {
            base.OnReset();
            this.dynEntity = null;
            _oldInteractType = 0;
            _questMarkEffect = null;
            _isExistActiveQuest = false;
            bvhBounds = default;
        }
    }
}
